package com.ibm.risk.irmp.workflow.client.flowable;

import com.ibm.risk.irmp.common.utils.BeanMapUtils;
import com.ibm.risk.irmp.workflow.client.flowable.model.RestVariable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ClassUtils;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.*;

@Slf4j
public class RestVarConvertor {

    public static List<RestVariable> toRestVariables(Map<String, Object> vars) {
        return toRestVariables(vars, null);
    }

    public static List<RestVariable> toRestVariables(Map<String, Object> vars, String scope) {
        List<RestVariable> vars2 = new ArrayList<>();
        if (vars != null) {
            for (Map.Entry<String, Object> e : vars.entrySet()) {
                log.trace("variable: {}", e);
                Object v = e.getValue();
                if (v != null) {
                    if (ClassUtils.isSimpleValueType(v.getClass()) || v instanceof Object[] || v instanceof Collection<?>) {
                        RestVariable vr = new RestVariable().name(e.getKey()).value(v).scope(scope);
                        vars2.add(vr);
//                    } else if (v instanceof Object[]) {
//
//                    } else if (v instanceof Collection<?>) {

                    } else {
                        Map<String, Object> map =
                                BeanMapUtils.beanToMap(v);
                        RestVariable vr = new RestVariable().name(e.getKey()).value(map);
                        vars2.add(vr);
                    }
                }
            }
        }
        return vars2;
    }

    public static Map<String, Object> convertToMap(List<RestVariable> variables) {
        Map<String, Object> vars = new HashMap<>();
        Authenticator auth = new Authenticator() {

            @Override

            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("admin", "test".toCharArray());
            }

        };
        try (HttpClient httpClient = HttpClient.newBuilder().authenticator(auth).build()) {
            for (RestVariable vr : variables) {
                log.trace("variable to map: {}", vr);
                if ("serializable".equals(vr.getType())) {
                    String url = vr.getValueUrl();

                    HttpRequest httpRequest = HttpRequest.newBuilder()
                            .uri(URI.create(url)).build();
                    HttpResponse<byte[]> resp = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofByteArray());
                    ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(resp.body()));
                    Object val = in.readObject();
                    if (val instanceof Map<?, ?>) {
                        val = BeanMapUtils.mapToBean((Map<?, ?>) val);
                    }
                    vars.put(vr.getName(), val);
                } else {
                    vars.put(vr.getName(), vr.getValue());
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return vars;
    }
}
